﻿//
// (C) Copyright 2009 Irantha Suwandarathna (iranthas@hotmail.com)
// All rights reserved.
//

/********************************************************
 * ADO.NET 2.0 Data Provider for SQLite Version 3.X
 * Written by Robert Simpson (robert@blackcastlesoft.com)
 * 
 ********************************************************/

using System;
using System.Data.Common;
using System.ComponentModel;
using System.Collections;
using System.Globalization;
using System.Reflection;

namespace System.Data.EffiProz
{
    [DefaultProperty("DataSource")]
    [DefaultMember("Item")]
    public sealed class EfzConnectionStringBuilder : DbConnectionStringBuilder
    {
         /// <summary>
    /// Properties of this class
    /// </summary>
    private Hashtable _properties;

    /// <overloads>
    /// Constructs a new instance of the class
    /// </overloads>
    /// <summary>
    /// Default constructor
    /// </summary>
    public EfzConnectionStringBuilder()
    {
      Initialize(null);
    }

    /// <summary>
    /// Constructs a new instance of the class using the specified connection string.
    /// </summary>
    /// <param name="connectionString">The connection string to parse</param>
    public EfzConnectionStringBuilder(string connectionString)
    {
      Initialize(connectionString);
    }

    /// <summary>
    /// Private initializer, which assigns the connection string and resets the builder
    /// </summary>
    /// <param name="cnnString">The connection string to assign</param>
    private void Initialize(string cnnString)
    {
      _properties = new Hashtable(StringComparer.OrdinalIgnoreCase);
      try
      {
        base.GetProperties(_properties);
      }
      catch(NotImplementedException)
      {
        FallbackGetProperties(_properties);
      }

      if (String.IsNullOrEmpty(cnnString) == false)
        ConnectionString = cnnString;
    }

    
    /// <summary>
    /// Gets/Sets the auto commit for the connection string.  The default is "False" which indicates auto commit true.
    /// </summary>
    [DisplayName("auto commit")]
    [Browsable(true)]
    [DefaultValue(true)]
    public bool AutoCommit
    {
      get
      {
        object value;
        TryGetValue("auto commit", out value);
        return Convert.ToBoolean(value);
      }
      set
      {
          this["auto commit"] = value;
      }
    }

    [DisplayName("auto shutdown")]
    [Browsable(true)]
    [DefaultValue(true)]
    public bool AutoShutdown
    {
        get
        {
            object value;
            TryGetValue("auto shutdown", out value);
            return Convert.ToBoolean(value);
        }
        set
        {
            this["auto shutdown"] = value;
        }
    }

    /// <summary>
    /// Gets/Sets whether or not to use connection pooling.  The default is "False"
    /// </summary>
    [DisplayName("pooling")]
    [Browsable(true)]
    [DefaultValue(false)]
    public bool Pooling
    {
      get
      {
        object value;
        TryGetValue("pooling", out value);
        return Convert.ToBoolean(value);
      }
      set
      {
        this["pooling"] = value;
      }
    }

    /// <summary>
    /// Gets/Sets whether or not to use connection pooling.  The default is "False"
    /// </summary>
    [DisplayName("ssl")]
    [Browsable(true)]
    [DefaultValue(false)]
    public bool Ssl
    {
        get
        {
            object value;
            TryGetValue("ssl", out value);
            return Convert.ToBoolean(value);
        }
        set
        {
            this["ssl"] = value;
        }
    }

    /// <summary>
    /// Gets/Sets whether or not to use connection pooling.  The default is "False"
    /// </summary>
    [DisplayName("ignore case")]
    [Browsable(true)]
    [DefaultValue(false)]
    public bool IgnoreCase
    {
      get
      {
        object value;
        TryGetValue("ignore case", out value);
        return Convert.ToBoolean(value);
      }
      set
      {
          this["ignore case"] = value;
      }
    }


    [DisplayName("readonly")]
    [Browsable(true)]
    [DefaultValue(false)]
    public bool ReadOnly
    {
        get
        {
            object value;
            TryGetValue("readonly", out value);
            return Convert.ToBoolean(value);
        }
        set
        {
            this["readonly"] = value;
        }
    }


    [DisplayName("referential intergrity")]
    [Browsable(true)]
    [DefaultValue(true)]
    public bool ReferentialIntergrity
    {
        get
        {
            object value;
            TryGetValue("referential intergrity", out value);
            return Convert.ToBoolean(value);
        }
        set
        {
            this["referential intergrity"] = value;
        }
    }

    /// <summary>
    /// Gets/Sets the datbase to open on the connection string.
    /// </summary>
    [DisplayName("data source")]
    [Browsable(true)]
    [DefaultValue("")]
    public string DataSource
    {
      get
      {
        object value;
        TryGetValue("data source", out value);
        return value.ToString();
      }
      set
      {
        this["data source"] = value;
      }
    }

    

         /// <summary>
    /// Gets/Sets the datbase to open on the connection string.
    /// </summary>
    [DisplayName("initial catalog")]
    [Browsable(true)]
    [DefaultValue("")]
    public string InitialCatalog
    {
        get
        {
            object value;
            TryGetValue("initial catalog", out value);
            return value.ToString();
        }
        set
        {
            this["initial catalog"] = value;
        }
    }

    /// <summary>
    /// Valid values:  Memory , File , Server
    /// </summary>
    [DefaultValue("memory")]
    [DisplayName("connection type")]
    [Browsable(true)]
    public string ConnectionType
    {
      get
      {
        object value;
        TryGetValue("connection type", out value);
        return value.ToString();
      }
      set
      {
          if (!value.Equals("memory", StringComparison.OrdinalIgnoreCase) &&
              !value.Equals("file", StringComparison.OrdinalIgnoreCase) &&
              !value.Equals("server", StringComparison.OrdinalIgnoreCase) &&
              !value.Equals("webserver", StringComparison.OrdinalIgnoreCase))
              throw new ArgumentException();
          this["connection type"] = value;
      }
    }

    /// <summary>
    /// Gets/sets the default command timeout for newly-created commands.  This is especially useful for 
    /// commands used internally such as inside a EffiProzDBTransaction, where setting the timeout is not possible.
    /// </summary>
    [DisplayName("command timeout")]
    [Browsable(true)]
    [DefaultValue(30)]
    public int DefaultTimeout
    {
      get
      {
        object value;
        TryGetValue("command timeout", out value);
        return Convert.ToInt32(value, CultureInfo.CurrentCulture);
      }
      set
      {
          this["command timeout"] = value;
      }
    }

    /// <summary>
    /// Determines whether or not the connection will automatically participate
    /// in the current distributed transaction (if one exists)
    /// </summary>
    [Browsable(true)]
    [DefaultValue(true)]
    [DisplayName("enlist")]
    public bool Enlist
    {
      get
      {
        object value;
        TryGetValue("enlist", out value);
        return Convert.ToBoolean(value);
      }
      set
      {
          this["enlist"] = value;
      }
    }
    

    /// <summary>
    /// Gets/sets the database user password
    /// </summary>
    [Browsable(true)]
    [PasswordPropertyText(true)]
    [DefaultValue("")]
    [DisplayName("password")]
    public string Password
    {
      get
      {
        object value;
        TryGetValue("password", out value);
        return value.ToString();
      }
      set
      {
        this["password"] = value;
      }
    }

    /// <summary>
    /// Gets/sets the database user name
    /// </summary>
    [Browsable(true)] 
    [DefaultValue("")]
    [DisplayName("user")]
    public string User
    {
        get
        {
            object value;
            TryGetValue("user", out value);
            return value.ToString();
        }
        set
        {
            this["user"] = value;
        }
    }

    /// <summary>
    /// Gets/Sets the Log size in MB.
    /// </summary>
    [DisplayName("log size")]
    [Browsable(true)]
    [DefaultValue(200)]
    public int LogSize 
    {
      get
      {
        object value;
        TryGetValue("log size", out value);
        return Convert.ToInt32(value, CultureInfo.CurrentCulture);
      }
      set
      {
          this["log size"] = value;
      }
    }

    /// <summary>
    /// Gets/Sets the maximum number of rows returned
    /// </summary>
    [DisplayName("max rows")]
    [Browsable(true)]
    [DefaultValue(0)]
    public int MaxPageCount
    {
      get
      {
        object value;
        TryGetValue("max rows", out value);
        return Convert.ToInt32(value, CultureInfo.CurrentCulture);
      }
      set
      {
          this["max rows"] = value;
      }
    }

   
    /// <summary>
    /// Sets the default isolation level for transactions on the connection.
    /// </summary>
    [Browsable(true)]
    [DefaultValue(IsolationLevel.ReadCommitted)]
    [DisplayName("isolation level")]
    public IsolationLevel DefaultIsolationLevel
    {
      get
      {
        object value;
        TryGetValue("isolation level", out value);
        if (value is string)
          return (IsolationLevel)TypeDescriptor.GetConverter(typeof(IsolationLevel)).ConvertFrom(value);
        else
          return (IsolationLevel)value;
      }
      set
      {
          this["isolation level"] = value;
      }
    }

    /// <summary>
    /// Helper function for retrieving values from the connectionstring
    /// </summary>
    /// <param name="keyword">The keyword to retrieve settings for</param>
    /// <param name="value">The resulting parameter value</param>
    /// <returns>Returns true if the value was found and returned</returns>
    public override bool TryGetValue(string keyword, out object value)
    {
      bool b = base.TryGetValue(keyword, out value);

      if (!_properties.ContainsKey(keyword)) return b;

      PropertyDescriptor pd = _properties[keyword] as PropertyDescriptor;

      if (pd == null) return b;

      // Attempt to coerce the value into something more solid
      if (b)
      {
        if (pd.PropertyType == typeof(Boolean))
          value = Convert.ToBoolean(value);
        else
          value = TypeDescriptor.GetConverter(pd.PropertyType).ConvertFrom(value);
      }
      else
      {
        DefaultValueAttribute att = pd.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
        if (att != null)
        {
          value = att.Value;
          b = true;
        }
      }
      return b;
    }

    /// <summary>
    /// Fallback method for MONO, which doesn't implement DbConnectionStringBuilder.GetProperties()
    /// </summary>
    /// <param name="propertyList">The hashtable to fill with property descriptors</param>
    private void FallbackGetProperties(Hashtable propertyList)
    {
      foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(this, true))
      {
        if (descriptor.Name != "ConnectionString" && propertyList.ContainsKey(descriptor.DisplayName) == false)
        {
          propertyList.Add(descriptor.DisplayName, descriptor);
        }
      }
    }
    }
}
